package chapter3;

import java.util.ArrayList;

/**
 * 这是一个抽象的迷宫类，这个类用二维数组表示
 * 
 * 0 = 空
 * 1 = 墙
 * 2 = 起始位置
 * 3 = 路径
 * 4 = 目标位置
 *
 * 这个类最重要的方法时scoreRoute 路线评分，这个方法返回一个路线的适应度评分，
 * 这个分数用来优化算法
 *
 */
public class Maze {
	//迷宫数组
	private final int maze[][];
	//起始位置初始化
	private int startPosition[] = { -1, -1 };

	//迷宫构造函数
	public Maze(int maze[][]) {
		this.maze = maze;
	}

	/**
	 * 获取迷宫的起始位置
	 * 1.若startPosition[] = { -1, -1 } 则直接返回
	 * 2.若不符合1，初始化startPosition[] = { 0, 0 }，然后寻找
	 * 迷宫坐标=2的位置即maze[rowIndex][colIndex] == 2，把这个坐标作为起始位置
	 * 3.若2没找到，则startPosition[] = { 0, 0 }
	 * 
	 * @return int[] x,y start position of maze
	 */
	public int[] getStartPosition() {
		// Check we already found start position
		if (this.startPosition[0] != -1 && this.startPosition[1] != -1) {
			return this.startPosition;
		}

		// Default return value
		int startPosition[] = { 0, 0 };

		// Loop over rows
		for (int rowIndex = 0; rowIndex < this.maze.length; rowIndex++) {
			// Loop over columns
			for (int colIndex = 0; colIndex < this.maze[rowIndex].length; colIndex++) {
				// 2 is the type for start position
				if (this.maze[rowIndex][colIndex] == 2) {
					this.startPosition = new int[] { colIndex, rowIndex };
					return new int[] { colIndex, rowIndex };
				}
			}
		}

		return startPosition;
	}

	/**
	 * 获取迷宫位置的值
	 * 
	 * @param x
	 *            position
	 * @param y
	 *            position
	 * @return int Position value
	 */
	public int getPositionValue(int x, int y) {
		if (x < 0 || y < 0 || x >= this.maze.length || y >= this.maze[0].length) {
			return 1;
		}
		return this.maze[y][x];
	}

	/**
	 * 检查是否是墙
	 *
	 * @param x
	 *            position
	 * @param y
	 *            position
	 * @return boolean
	 */
	public boolean isWall(int x, int y) {
		return (this.getPositionValue(x, y) == 1);
	}

	/**
	 * 检查是否是路径
	 *
	 * @param x
	 *            position
	 * @param y
	 *            position
	 * @return boolean
	 */
	public boolean isRouter(int x, int y) {
		return (this.getPositionValue(x, y) == 3);
	}

	/**
	 * x坐标最大值
	 * 
	 * @return int Max index
	 */
	public int getMaxX() {
		return this.maze[0].length - 1;
	}

	/**
	 * y坐标的最大值
	 * 
	 * @return int Max index
	 */
	public int getMaxY() {
		return this.maze.length - 1;
	}

	/**
	 * 迷宫路线评分方法
	 * 
	 * 该方法检查路由数组ArrayList<int[]> route
	 * 1.访问路径正确计1分，正确即maze[step[1]][step[0]] == 3
	 * 2.重复访问同一位置不加分，所以需要visited[][]这个数组来记录是否访问过。
	 *
	 * @return int Max index
	 */
	public int scoreRoute(ArrayList<int[]> route) {
		int score = 0;
		boolean visited[][] = new boolean[this.getMaxY() + 1][this.getMaxX() + 1];

		// Loop over route and score each move
		for (Object routeStep : route) {
			int step[] = (int[]) routeStep;
			if (this.maze[step[1]][step[0]] == 3 && visited[step[1]][step[0]] == false) {
				// Increase score for correct move
				score++;
				// Remove reward
				visited[step[1]][step[0]] = true;
			}
		}

		return score;
	}
}
